"use strict";
import { DeviceEventEmitter, AppRegistry, EmitterSubscription, NativeEventEmitter } from 'react-native';
import { NativeEventListener } from 'rtn-supernote-plugin-core/src/listener/NativeEventListener';
import NativeEvent from 'rtn-supernote-plugin-core/src/module/NativeEvent';
import { SidebarEntrance, EditBarEntrance } from 'rtn-supernote-plugin-core/src/bean/Entrance';
import { EntranceType } from 'rtn-supernote-plugin-core/src/bean/Entrance';
import NativeFileUtils from 'rtn-supernote-plugin-core/src/module/NativeFileUtils';
import NativePluginManager from 'rtn-supernote-plugin-core/src/module/NativePluginManager';
import { MenuItemEvent, MenuItemListener, MenuItemSubscription } from 'rtn-supernote-plugin-core/src/listener/MenuItemListener';
import { ConfigButtonListener, ConfigButtonSubscription } from 'rtn-supernote-plugin-core/src/listener/ConfigButtonListener';
import {PluginEventListener, PluginEventSubscription} from 'rtn-supernote-plugin-core/src/listener/PluginEventListener';

const NativeEventType = {
  start: 1,
  stop: 2,
};

interface NativeEventSubs {
  id: number;
  listener: NativeEventListener;
  remove: () => void;
};
const pluginEvent = "plugin_event";
const pluginEventType = "event_type";

const START_TYPE = "start_type";
const LEFT = "left";
const TOP = "top";
const RIGHT = "right";
const BOTTOM = "bottom";
// Button event listener
const PLUGIN_MENU_ITEM_EVENT = "plugin_menu_item_event";
const PLUGIN_CONFIG_EVENT = "plugin_config_event";
// Listen for language changes
const PLUGIN_EVENT_LANG = "plugin_event_lang";
var pluginTask = "plugin_task";
var taskId = 100011;

let lastMsg;
let eventListenerIdCount = 0;
const nativeEventSubscriptions = new Map();
/// Whether notification has been sent during listener addition
let addNotifyIds = [];

/// Timer to delay clearing lastMsg
var timeMsg;
let isInit = false;

/// Whether notification has been sent during listener addition
let addMenuNotifyIds = [];
// Last event received
var lastMenuEventMsg = null;
// Timer to delay clearing lastMenuEventMsg
var timeMenuEvent;
// Collection of button event listener subscriptions
const menuEventSubscriptions = new Map();
// Counter for button listener subscription IDs
let menuEventSubIdCount = 0;

/// Whether notification has been sent during listener addition
let addConfigNotifyIds = [];
// Last event received
var lastConfigEventMsg = null;
// Timer to delay clearing lastMenuEventMsg
var timeConfigEvent;
// Collection of button event listener subscriptions
const configSubscriptions = new Map();
// Counter for button listener subscription IDs
let configEventSubIdCount = 0;

// Last language change data received
var lastLanEventMsg = null;
const langSubscriptions = new Map();
let langEventSubIdCount = 0;

const eventEmitter = new NativeEventEmitter();

/// Callback task
async function PluginTask(data) {
  console.log("PluginTask run data:" + data);
  // Add menu button listener
  addMenuEventListener();
  addConfigButtonListener();
  addLangListener();
  DeviceEventEmitter.addListener(pluginEvent, (msg) => {
    console.log("PluginTask msg:" + msg.event_type);
    console.log("PluginTask eventListenerIdCount:" + eventListenerIdCount);
    if (timeMsg != null && timeMsg != undefined) {
      clearTimeout(timeMsg);
    }
    addNotifyIds = null;

    lastMsg = msg;
    notifyAllListener(msg);

    timeMsg = setTimeout(function () {
      lastMsg = null;
      timeMsg = null;
      addNotifyIds = null;
    }, 1000);
  });
};

// Listen for language changes
const addLangListener = () => {
  eventEmitter.addListener(PLUGIN_EVENT_LANG,
    (msg) => {
      console.log("lang msg:" + msg);
      for (let [key, value] of langSubscriptions) {
        value.listener.onMsg(msg);
      }
    }
  )
}

// Add configuration button listener
const addConfigButtonListener = () => {
  eventEmitter.addListener(PLUGIN_CONFIG_EVENT,
    (msg) => {
      console.log("Config button msg:" + msg);
      if (timeConfigEvent != null && timeConfigEvent != undefined) {
        clearTimeout(timeConfigEvent);
      }
      addConfigNotifyIds = null;
      lastConfigEventMsg = 8;
      for (let [key, value] of configSubscriptions) {
        // addNotifyIds is asynchronous, so check if notification has been sent during asynchronous addition
        if (addConfigNotifyIds != null && addConfigNotifyIds.length > 0
          && addConfigNotifyIds.includes(key)
        ) {
          continue;
        }
        value.listener.onClick();
      }
      timeConfigEvent = setTimeout(function () {
        lastConfigEventMsg = null;
        timeConfigEvent = null;
        addConfigNotifyIds = null;
      }, 1000);
    }
  );
};

/// Add button event listener
const addMenuEventListener = () => {
  eventEmitter.addListener(PLUGIN_MENU_ITEM_EVENT,
    (msg) => {
      console.log("MenuEvent msg:" + msg);
      if (timeMenuEvent != null && timeMenuEvent != undefined) {
        clearTimeout(timeMenuEvent);
      }
      addMenuNotifyIds = null;
      lastMenuEventMsg = msg;
      for (let [key, value] of menuEventSubscriptions) {
        // addNotifyIds is asynchronous, so check if notification has been sent during asynchronous addition
        if (addMenuNotifyIds != null && addMenuNotifyIds.length > 0
          && addMenuNotifyIds.includes(key)) {
          continue;
        }
        // Notify message
        value.listener.onMenuItemPress(msg);
      }

      timeMenuEvent = setTimeout(function () {
        lastMenuEventMsg = null;
        timeMenuEvent = null;
        addMenuNotifyIds = null;
      }, 1000);

    }
  );

};

const notifyAllListener = (msg: any) => {
  console.log("PluginTask map size:" + nativeEventSubscriptions.size);
  for (let [key, value] of nativeEventSubscriptions) {
    console.log("PluginTask map notifyEvent key:" + key);
    /// Check if notification has been sent during addition
    if (addNotifyIds != null && addNotifyIds.length > 0
      && addNotifyIds.includes(key)
    ) {
      continue;
    }

    notifyEvent(value.listener, msg);
  }
};


const notifyEvent = (listener: NativeEventListener, msg: any) => {
  if (listener == null) {
    return;
  }
  console.log("notifyEvent msg type:" + msg.event_type);
  switch (msg.event_type) {
    case NativeEventType.start:
      listener.onStart(msg.plugin_action);
      break;
    case NativeEventType.stop:
      console.log("notifyEvent onStop listener:" + listener);
      listener.onStop();
      break;
  }
}


const PluginManager = {
  /* init(): void {
    if (isInit) {
      return;
    }
    isInit = true;
    NativeEvent?.onMounted();
    AppRegistry.registerHeadlessTask(pluginTask, () => PluginTask);
    AppRegistry.startHeadlessTask(taskId, pluginTask, "Task");
  }, */

  async init(): void {
    console.log("PluginManager init");
    if (isInit) {
      return;
    }
    var initFlag = true;

    if (initFlag) {
      isInit = true;
      NativeEvent?.onMounted();
      AppRegistry.registerHeadlessTask(pluginTask, () => PluginTask);
      AppRegistry.startHeadlessTask(taskId, pluginTask, "Task");
    }

  },


  addEventListener(listener: NativeEventListener): NativeEventSubs {
    console.log("addEventListener:");
    var id = eventListenerIdCount++;
    const subscription: NativeEventSubs = ({
      id: id,
      listener: listener,
      remove: () => {
        console.log("subscription remove id:" + id);
        nativeEventSubscriptions.delete(id);
      }
    });
    nativeEventSubscriptions.set(id, subscription);
    console.log("addEventListener end eventListenerIdCount:" + id +
      "===" + nativeEventSubscriptions.size
    );
    /// Add listener may be later than message arrives, need to send a message
    if (lastMsg != null && lastMsg != undefined) {
      if (addNotifyIds == null) {
        addNotifyIds = [id];
      } else {
        addNotifyIds.push(id);
      }
      notifyEvent(listener, lastMsg);
    }
    return subscription;
  },

  registerMenuItemEventListener(menuItemListener: MenuItemListener): MenuItemSubscription {
    var id = menuEventSubIdCount++;
    const subscription: MenuItemSubscription = ({
      id: id,
      listener: menuItemListener,
      remove: () => {
        console.log("registerMenuItemEventListener remove id:" + id);
        menuEventSubscriptions.delete(id);
      }
    });
    menuEventSubscriptions.set(id, subscription);
    console.log("registerMenuItemEventListener end eventListenerIdCount:" + id +
      "===" + menuEventSubscriptions.size
    );
    console.log("registerMenuItemEventListener lastMenuEventMsg:" + JSON.stringify(lastMenuEventMsg));

    // Add listener may be later than message arrives, need to send a message
    if (lastMenuEventMsg != null && lastMenuEventMsg != undefined) {
      if (addMenuNotifyIds == null) {
        addMenuNotifyIds = [id];
      } else {
        addMenuNotifyIds.push(id);
      }
      menuItemListener.onMenuItemPress(lastMenuEventMsg);
    }


    return subscription;

  },
  registerConfigButtonListener(buttonListener: ConfigButtonListener): ConfigButtonSubscription {
    var id = configEventSubIdCount++;
    const subscription: ConfigButtonSubscription = ({
      id: id,
      listener: buttonListener,
      remove: () => {
        configSubscriptions.delete(id);
      }
    });
    configSubscriptions.set(id, subscription);
    if (lastConfigEventMsg != null && lastConfigEventMsg != undefined) {
      if (addConfigNotifyIds == null) {
        addConfigNotifyIds = [id];
      } else {
        addConfigNotifyIds.push(id);
      }
      buttonListener.onClick();
    }
  },
  registerLangListener(langListener:PluginEventListener):PluginEventSubscription{
    var id = langEventSubIdCount++;
    const subscription:PluginEventSubscription =({
      id:id,
      listener:langListener,
      remove:()=>{
        langSubscriptions.delete(id);
      }
    });
    langSubscriptions.set(id, subscription);
  }

};

module.exports = PluginManager;
